package com.littleken.foodieCommon.Utils;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.littleken.foodieCommon.bean.DataList;
import net.sf.cglib.beans.BeanCopier;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class BeanCopierUtil {

    /**
     * BeanCopier享元缓存池
     */
    private static Map<String, BeanCopier> cacheMap = new ConcurrentHashMap<>();

    /**
     * 获取beanCopier实例
     *
     * @param sourceClass 源类
     * @param targetClass 目标类
     * @return beanCopier
     */
    private static <T, E> BeanCopier getBeanCopier(Class<T> sourceClass, Class<E> targetClass) {
        String beanKey = sourceClass.toString() + targetClass.toString();
        BeanCopier beanCopier;
        if (!cacheMap.containsKey(beanKey)) {
            synchronized (BeanCopierUtil.class) {
                if (!cacheMap.containsKey(beanKey)) {
                    beanCopier = BeanCopier.create(sourceClass, targetClass, false);
                    cacheMap.put(beanKey, beanCopier);
                } else {
                    beanCopier = cacheMap.get(beanKey);
                }
            }
        } else {
            beanCopier = cacheMap.get(beanKey);
        }
        return beanCopier;
    }

    /**
     * 将source对象属性拷贝到target对象中去
     *
     * @param source 源对象
     * @param target 目标对象
     */
    public static void copyProperties(Object source, Object target) {
        BeanCopier beanCopier = getBeanCopier(source.getClass(), target.getClass());
        beanCopier.copy(source, target, null);
    }

    /**
     * 克隆对象
     *
     * @param source 源对象
     * @param clazz  目标类
     * @return 克隆后的对象
     */
    public static <T> T copy(Object source, Class<T> clazz) {
        if (source == null) {
            return null;
        }
        T target;
        try {
            target = clazz.newInstance();
            copyProperties(source, target);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
        return target;
    }

    /**
     * 复制list
     *
     * @param sources 源对象list
     * @param clazz   目标类
     * @return 克隆后的对象list
     */
    public static <T> List<T> copyList(List<?> sources, Class<T> clazz) {
        if (sources == null) {
            return null;
        }
        List<T> targets = new ArrayList<>(sources.size());
        if (!sources.isEmpty()) {
            sources.forEach(source -> {
                T clone = copy(source, clazz);
                targets.add(clone);
            });
        }
        return targets;
    }

    /**
     * page to DataList
     *
     * @param page mybatisPlus分页查询返回的Page对象
     * @return DataList
     */
    public static <T> DataList<T> toDataList(Page<T> page) {
        DataList<T> dataList = new DataList<>();
        dataList.setPageNo(page.getCurrent());
        dataList.setPageSize(page.getSize());
        dataList.setTotal(page.getTotal());
        dataList.setList(page.getRecords());
        return dataList;
    }

    /**
     * page to DataList
     *
     * @param page  mybatisPlus分页查询返回的Page对象
     * @param clazz page中的List要beanCope的目标类型
     * @return DataList
     */
    public static <T> DataList<T> toDataList(Page<?> page, Class<T> clazz) {
        DataList<T> dataList = new DataList<>();
        dataList.setPageNo(page.getCurrent());
        dataList.setPageSize(page.getSize());
        dataList.setTotal(page.getTotal());
        dataList.setList(BeanCopierUtil.copyList(page.getRecords(), clazz));
        return dataList;
    }

    /**
     * page to DataList
     */
    public static <T> DataList<T> toDataList(DataList<?> sourceDataList, Class<T> clazz) {
        if (sourceDataList == null) {
            return null;
        }
        DataList<T> dataList = copy(sourceDataList, DataList.class);
        if (!sourceDataList.getList().isEmpty()) {
            dataList.setList(BeanCopierUtil.copyList(sourceDataList.getList(), clazz));
        }
        return dataList;
    }

}